#include "QNeuronWindow.h"

int QNeuronWindow::getNearestNeuron(QPointF point)
{
    int nearestNumb = -1;
    for (int i=0; i<nerveList.size(); ++i)
    {
        if ((nerveList[i]->getType())&&(nerveList[i]->getType()<4))
        {
            if (pow(pow(nerveList[i]->getPos().x()-point.x(),2)+pow(nerveList[i]->getPos().y()-point.y(),2),0.5)<3)
            {
                nearestNumb = i;
            }
        }
    }
    return nearestNumb;
}

void QNeuronWindow::createActions(void)
{
    newAction = new QAction("New", this);
    newAction->setShortcuts(QKeySequence::New);
    newAction->setStatusTip(tr("Create a new file"));
    connect(newAction, SIGNAL(triggered()), this, SLOT(reset()));

    loadAction = new QAction("Open", this);
    loadAction->setShortcuts(QKeySequence::Open);
    connect(loadAction, SIGNAL(triggered()), this, SLOT(load()));

    saveAction = new QAction("Save", this);
    saveAction->setShortcuts(QKeySequence::Save);
    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));

    stabilisationAction = new QAction("Stabilisation", this);
    stabilisationAction->setShortcut(tr("Ctrl+Z"));
    connect(stabilisationAction, SIGNAL(triggered()), this, SLOT(stabilisation()));

    acceptAction = new QAction("Accept changes", this);
    acceptAction->setShortcut(tr("Ctrl+A"));
    acceptAction->setStatusTip("Action will affect only if this editor window called from 'Node' edit option");
    acceptAction->setDisabled(true);
    connect(acceptAction, SIGNAL(triggered()), this, SLOT(acceptChanges()));

    exitAction = new QAction("Exit", this);
    exitAction->setShortcut(tr("Ctrl+Q"));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));

    freeAction = new QAction("Move", this);
    freeAction->setShortcut(tr("Alt+F"));
    freeAction->setCheckable(true);
    connect(freeAction, SIGNAL(triggered()), this, SLOT(setMode0()));


    neuronAction = new QAction("Neuron", this);
    neuronAction->setCheckable(true);
    connect(neuronAction, SIGNAL(triggered()), this, SLOT(setMode1()));
    neuronAction->setShortcut(tr("Alt+N"));

    receptorAction = new QAction("Receptor", this);
    receptorAction->setCheckable(true);
    connect(receptorAction, SIGNAL(triggered()), this, SLOT(setMode2()));
    receptorAction->setShortcut(tr("Alt+R"));

    transmitterAction = new QAction("Transmitter", this);
    transmitterAction->setCheckable(true);
    connect(transmitterAction, SIGNAL(triggered()), this, SLOT(setMode3()));
    transmitterAction->setShortcut(tr("Alt+T"));

    electricSynapseAction = new QAction("Electric Synapse", this);
    electricSynapseAction->setCheckable(true);
    connect(electricSynapseAction, SIGNAL(triggered()), this, SLOT(setMode4()));
    electricSynapseAction->setShortcut(tr("Alt+E"));

    inhibitorSynapseAction = new QAction("Inhibitor Synapse", this);
    inhibitorSynapseAction->setCheckable(true);
    connect(inhibitorSynapseAction, SIGNAL(triggered()), this, SLOT(setMode5()));
    inhibitorSynapseAction->setShortcut(tr("Alt+I"));

    chemicalSynapseAction = new QAction("Chemical Synapse", this);
    chemicalSynapseAction->setCheckable(true);
    connect(chemicalSynapseAction, SIGNAL(triggered()), this, SLOT(setMode6()));
    chemicalSynapseAction->setShortcut(tr("Alt+C"));

    showReceptorPotentialAction = new QAction("Show Receptor Potential", this);
    showReceptorPotentialAction->setShortcut(tr("Alt+1"));
    showReceptorPotentialAction->setCheckable(true);
    connect(showReceptorPotentialAction, SIGNAL(toggled(bool)), this, SLOT(showReceptorPotential(bool)));

    showSynapseDirectionAction = new QAction("Show Synapse Direction", this);
    showSynapseDirectionAction->setCheckable(true);
    showSynapseDirectionAction->setShortcut(tr("Alt+2"));
    connect(showSynapseDirectionAction, SIGNAL(toggled(bool)), this, SLOT(showSynapseDirection(bool)));

    showRelaxTimeAction = new QAction("Show Relax Time", this);
    showRelaxTimeAction->setCheckable(true);
    showRelaxTimeAction->setShortcut(tr("Alt+3"));
    connect(showRelaxTimeAction, SIGNAL(toggled(bool)), this, SLOT(showRelaxTime(bool)));

    helpAction = new QAction("Help", this);
    connect(helpAction, SIGNAL(triggered()), this, SLOT(help()));

    aboutAction = new QAction("About", this);
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));

    aboutQtAction = new QAction("About Qt", this);
    connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}
void QNeuronWindow::createMenus(void)
{
    fileMenu = new QMenu;
    fileMenu = menuBar()->addMenu("File");
    fileMenu->addAction(newAction);
    fileMenu->addAction(loadAction);
    fileMenu->addAction(saveAction);
    fileMenu->addSeparator();
    fileMenu->addAction(stabilisationAction);
    fileMenu->addSeparator();
    fileMenu->addAction(acceptAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);

    modeMenu = new QMenu;
    modeMenu = menuBar()->addMenu("Mode");
    modeMenu->addAction(freeAction);
    modeMenu->addAction(neuronAction);
    modeMenu->addAction(receptorAction);
    modeMenu->addAction(transmitterAction);
    modeMenu->addAction(electricSynapseAction);
    modeMenu->addAction(inhibitorSynapseAction);
    modeMenu->addAction(chemicalSynapseAction);

    viewMenu = new QMenu;
    viewMenu = menuBar()->addMenu("View");
    viewMenu->addAction(showReceptorPotentialAction);
    viewMenu->addAction(showSynapseDirectionAction);
    viewMenu->addAction(showRelaxTimeAction);

    helpMenu = new QMenu;
    helpMenu = menuBar()->addMenu("About");
    helpMenu->addAction(helpAction);
    helpMenu->addAction(aboutAction);
    helpMenu->addAction(aboutQtAction);
}
void QNeuronWindow::createPlotWidget(void)
{
    plot = new QPlot;

    plotDock = new QDockWidget(tr("Plot"), this);
    viewMenu->addAction(plotDock->toggleViewAction());
    plotDock->setAllowedAreas(Qt::BottomDockWidgetArea);
    plotDock->setContentsMargins(1,0,1,0);
    plotDock->setWidget(plot);
    this->addDockWidget(Qt::BottomDockWidgetArea, plotDock);
}
void QNeuronWindow::createPropertyWidget(void)
{
    propertyWidget = new QPropertyWidget;
    propertyWidget->setMinimumWidth(200);
    connect(propertyWidget, SIGNAL(removeNerveSignal(int)), this, SLOT(removeNerve(int)));
    connect(propertyWidget, SIGNAL(addNerveCurve(int)), this, SLOT(addCurve(int)));
    connect(propertyWidget, SIGNAL(removeNerveCurve(int)), this, SLOT(removeCurve(int)));
    connect(propertyWidget, SIGNAL(gridStepChanged(int)), this, SLOT(setGridStep(int)));
    connect(propertyWidget, SIGNAL(bindingChanged(bool)), this, SLOT(setBinding(bool)));

    propertyDock = new QDockWidget(tr("Properties"), this);
    viewMenu->addAction(propertyDock->toggleViewAction());
    propertyDock->setAllowedAreas(Qt::RightDockWidgetArea);
    propertyDock->setWidget(propertyWidget);
    this->addDockWidget(Qt::RightDockWidgetArea, propertyDock);
}
void QNeuronWindow::createStatusBar(void)
{
    this->statusBar()->addWidget(statusLabel);
    this->statusBar()->setAutoFillBackground(true);
}

void QNeuronWindow::createNeuron(QPointF _pos)
{
    QNeuron *tempNeuron = new QNeuron;
    tempNeuron->setPos(_pos);
    tempNeuron->setID(nerveList.size());
    nerveList << tempNeuron;
    propertyWidget->addItem(nerveList.last());
    exNerveListLength++;
}
void QNeuronWindow::createReceptor(QPointF _pos)
{
    QReceptor *tempReceptor = new QReceptor;
    tempReceptor->setPos(_pos);
    tempReceptor->setID(nerveList.size());
    nerveList << tempReceptor;
    propertyWidget->addItem(nerveList.last());
    exNerveListLength++;
}
void QNeuronWindow::createTransmitter(QPointF _pos)
{
    QTransmitter *tempTransmitter = new QTransmitter;
    tempTransmitter->setPos(_pos);
    tempTransmitter->setID(nerveList.size());
    nerveList << tempTransmitter;
    propertyWidget->addItem(nerveList.last());
    exNerveListLength++;
}
void QNeuronWindow::createElectricSynapse(QNerveTissue* sender, QNerveTissue* receiver)
{
    QElectricSynapse *tempElectricSynapse = new QElectricSynapse;
    tempElectricSynapse->addReceiver(receiver);
    tempElectricSynapse->setID(nerveList.size());
    nerveList << tempElectricSynapse;

    sender->addReceiver(nerveList.last());
    propertyWidget->addItem(nerveList.last());
    exNerveListLength++;
}
void QNeuronWindow::createInhibitorSynapse(QNerveTissue* sender, QNerveTissue* receiver)
{
    QInhibitorSynapse *tempInhibitorSynapse = new QInhibitorSynapse;
    tempInhibitorSynapse->addReceiver(receiver);
    tempInhibitorSynapse->setID(nerveList.size());
    nerveList << tempInhibitorSynapse;

    sender->addReceiver(nerveList.last());
    propertyWidget->addItem(nerveList.last());
    exNerveListLength++;
}
void QNeuronWindow::createChemicalSynapse(QNerveTissue* sender, QNerveTissue* receiver)
{
    QChemicalSynapse *tempChemicalSynapse = new QChemicalSynapse;
    tempChemicalSynapse->addReceiver(receiver);
    tempChemicalSynapse->setID(nerveList.size());
    nerveList << tempChemicalSynapse;

    sender->addReceiver(nerveList.last());
    propertyWidget->addItem(nerveList.last());
    exNerveListLength++;
}

void QNeuronWindow::spreadImpulse()
{
    t++;

    int curveId = 0;

    for (int i=0; i<nerveList.size(); ++i)
    {
        if (nerveList[i]->isCurveVisible())
        {
            if (t%5==0)
            {
                plot->addPoint(QPointF(t/5, maxValue[i]), curveId);
                curveId++;
            }
            else if ((t-1)%5==0)
            {
                maxValue[i] = nerveList[i]->getMemPot();
            }
            else
            {
                if (qAbs(nerveList[i]->getMemPot())>qAbs(maxValue[i]))
                {
                    maxValue[i] = nerveList[i]->getMemPot();
                }
            }
        }
    }
    if (t%5==0) plot->update();
    if (t%100==0) this->update();
}

QNeuronWindow::QNeuronWindow(void): exNerveListLength(0), t(0)
{
    maxListCount = 100;
    maxValue = new double[maxListCount];
    for (int i=0; i<maxListCount; ++i)
    {
        maxValue[i] = 0;
    }

    statusLabel = new QLabel;

    centralWidget = new QWidget;
    centralWidget->setMinimumSize(400, 400);
    this->setCentralWidget(centralWidget);

    this->createActions();
    this->createMenus();
    this->createPlotWidget();
    this->createPropertyWidget();
    this->createStatusBar();
    this->setMode0();

    hasBinding = false;
    nodeDraw = false;

    receptorPotentialVisible = false;
    synapseDirectionVisible = false;
    relaxTimeVisible = false;

    moveNeuronCount = -1;
    gridStep = 20;
}
void QNeuronWindow::setNerveList(QList<QNerveTissue*> _nerveList)
{
    this->reset();
    acceptAction->setDisabled(false);

    nerveList = _nerveList;
    exNerveListLength = nerveList.length();
    this->fillPropertyWidget();
    this->update();
}
QColor QNeuronWindow::setColorByType(int type)
{
    switch (type)
    {
    case 1:
        return QColor(Qt::blue);
        break;
    case 2:
        return QColor(Qt::red);
        break;
    case 3:
        return QColor(0,127,0);
        break;
    case 4:
        return QColor(0,0,0);
        break;
    case 5:
        return QColor(0,127,255);
        break;
    case 6:
        return QColor(255,127,0);
        break;
    default:
        return QColor(Qt::black);
    }
}
QDomElement QNeuronWindow::xmlAddNerve(QDomDocument* xmlFile, QNerveTissue *nerve)
{
    nerve->updateReceiverIDList();

    QDomElement nodeElement = xmlFile->createElement("NERVE");
    nodeElement.setAttribute("id", nerve->getID());
    nodeElement.setAttribute("type", nerve->getType());
    nodeElement.setAttribute("curve-vis", nerve->isCurveVisible());
    nodeElement.setAttribute("is-sender", nerve->isSender());

    QString receiverString;
    for (int i=0; i<nerve->getReceiverIDList().length(); ++i)
    {
        receiverString += QString().setNum(nerve->getReceiverIDList()[i])+";";
    }

    nodeElement.setAttribute("receiver-list", receiverString);

    switch (nerve->getType())
    {
    case 1:
        nodeElement.setAttribute("pos-x", nerve->getPos().x());
        nodeElement.setAttribute("pos-y", nerve->getPos().y());
        break;
    case 2:
        nodeElement.setAttribute("pos-x", nerve->getPos().x());
        nodeElement.setAttribute("pos-y", nerve->getPos().y());
        nodeElement.setAttribute("receptor-pot", nerve->getMemPot());
        nodeElement.setAttribute("receptor-switched-on", nerve->isSwitchedOn());
        break;
    case 3:
        nodeElement.setAttribute("pos-x", nerve->getPos().x());
        nodeElement.setAttribute("pos-y", nerve->getPos().y());
        break;
    case 4:
        nodeElement.setAttribute("resistance", nerve->getMultiplier());
        break;
    case 5:
        nodeElement.setAttribute("relax-time", nerve->getRelaxTime());
        break;
    case 6:
        nodeElement.setAttribute("relax-time", nerve->getRelaxTime());
        break;
    }
    return nodeElement;
}

void QNeuronWindow::paintEvent(QPaintEvent * /*event*/)
{
    QPainter painter(this);

    painter.setPen(QColor(220,220,220));
    painter.setBrush(QColor(247,247,247));
    painter.drawRect(0,20,centralWidget->width()-1,centralWidget->height()-1);

    painter.setPen(QColor(219,219,219));

    for(int i=0; i<=floor((centralWidget->width()-1)/gridStep); ++i)
    {
        painter.drawLine(gridStep*i, 0, gridStep*i, centralWidget->height()+19);
    }
    for(int i=0; i<=floor((centralWidget->height()-1)/gridStep); ++i)
    {
        painter.drawLine(0, 19+gridStep*i, centralWidget->width()-1, 19+gridStep*i);
    }

    for (int i=0; i<nerveList.size(); ++i)
    {
        painter.setPen(this->setColorByType(nerveList[i]->getType()));
        switch (nerveList[i]->getType())
        {
        case 1:
            painter.drawEllipse(nerveList[i]->getPos(), 3, 3);
            painter.drawText(QPointF(nerveList[i]->getPos().x()+5,nerveList[i]->getPos().y()-5),QString().setNum(nerveList[i]->getID()));
            break;
        case 2:
            painter.drawRect(nerveList[i]->getPos().x()-3,nerveList[i]->getPos().y()-3,6,6);

            if (receptorPotentialVisible) receptorPotentialStr = "["+QString().setNum(nerveList[i]->getMemPot())+"]";
            else receptorPotentialStr = QString();

            painter.drawText(QPointF(nerveList[i]->getPos().x()+5,nerveList[i]->getPos().y()-5),QString().setNum(nerveList[i]->getID())+" "+receptorPotentialStr);
            break;
        case 3:
            QVector<QPoint> transmitterVector;
            transmitterVector << QPoint(nerveList[i]->getPos().x(),nerveList[i]->getPos().y()-3);
            transmitterVector << QPoint(nerveList[i]->getPos().x()-3,nerveList[i]->getPos().y()+3);
            transmitterVector << QPoint(nerveList[i]->getPos().x()+3,nerveList[i]->getPos().y()+3);
            transmitterVector << QPoint(nerveList[i]->getPos().x(),nerveList[i]->getPos().y()-3);
            painter.drawPolyline(QPolygon(transmitterVector));
            painter.drawText(QPointF(nerveList[i]->getPos().x()+5,nerveList[i]->getPos().y()-5), QString().setNum(nerveList[i]->getID()));
            break;
        }
        if ((nerveList[i]->getType())&&(nerveList[i]->getType()<4))
        {
            for (int j=0; j<nerveList[i]->getReceiverList().size(); ++j)
            {
                painter.setPen(QNeuronWindow::setColorByType(nerveList[i]->getReceiverList()[j]->getType()));
                painter.drawLine(nerveList[i]->getPos(),nerveList[i]->getReceiverList()[j]->getReceiverList().first()->getPos());

                synapseDirectionStr = QString();
                relaxTimeStr = QString();

                if (synapseDirectionVisible) synapseDirectionStr = "("+QString().setNum(nerveList[i]->getID())+"-"+QString().setNum(nerveList[i]->getReceiverList()[j]->getReceiverList().first()->getID())+")";

                if (relaxTimeVisible)
                {
                    if (nerveList[i]->getReceiverList()[j]->getType() == 5) relaxTimeStr = "<"+QString().setNum(nerveList[i]->getReceiverList()[j]->getRelaxTime())+">";
                    else if (nerveList[i]->getReceiverList()[j]->getType() == 6) relaxTimeStr = "{"+QString().setNum(nerveList[i]->getReceiverList()[j]->getRelaxTime())+"}";
                }

                painter.drawText(QPointF(5+0.5*(nerveList[i]->getPos().x()+nerveList[i]->getReceiverList()[j]->getReceiverList().first()->getPos().x()),
                                         -5+0.5*(nerveList[i]->getPos().y()+nerveList[i]->getReceiverList()[j]->getReceiverList().first()->getPos().y())),
                                 QString().setNum(nerveList[i]->getReceiverList()[j]->getID())+synapseDirectionStr+" "+relaxTimeStr);
            }
        }
    }
    if (nodeDraw)
    {
        painter.setPen(QPen(this->setColorByType(mode)));
        painter.drawLine(nodeStart, nodeFinish);
    }
}
void QNeuronWindow::mouseMoveEvent(QMouseEvent *event)
{
    QPointF bindingPos = QPointF(0,0);
    if(hasBinding) bindingPos = QPoint(gridStep*int(event->posF().x()/gridStep+0.5), 19+gridStep*int((event->posF().y()-19)/gridStep+0.5));
    else bindingPos = event->posF();

    if (moveNeuronCount>=0) nerveList[moveNeuronCount]->setPos(bindingPos);
    nodeFinish = event->posF();

    this->update();
}
void QNeuronWindow::mousePressEvent(QMouseEvent *event)
{
    nodeDraw = false;

    QPointF bindingPos = QPointF(0,0);
    if(hasBinding) bindingPos = QPoint(gridStep*int(event->posF().x()/gridStep+0.5), 19+gridStep*int((event->posF().y()-19)/gridStep+0.5));
    else bindingPos = event->posF();

    if(hasBinding)
    {

    }
    switch (mode)
    {
    case 0:
        moveNeuronCount = this->getNearestNeuron(event->posF());
        if (moveNeuronCount>=0)
        {
            propertyWidget->selectNerve(moveNeuronCount);
        }
        break;
    case 1:
        if (this->getNearestNeuron(bindingPos)<0) this->createNeuron(bindingPos);
        break;
    case 2:
        if (this->getNearestNeuron(bindingPos)<0) this->createReceptor(bindingPos);
        break;
    case 3:
        if (this->getNearestNeuron(bindingPos)<0) this->createTransmitter(bindingPos);
        break;
    case 4:
        nodeDraw = true;
        nodeStart = bindingPos;
        nodeFinish = bindingPos;
        break;
    case 5:
        nodeDraw = true;
        nodeStart = bindingPos;
        nodeFinish = bindingPos;
        break;
    case 6:
        nodeDraw = true;
        nodeStart = bindingPos;
        nodeFinish = bindingPos;
        break;
    }
    this->update();
}
void QNeuronWindow::mouseReleaseEvent(QMouseEvent * /*event*/)
{
    switch (mode)
    {
    case 0:
        moveNeuronCount = -1;
        break;
    case 4:
        if (nodeDraw&&((getNearestNeuron(nodeStart)>=0)&&(getNearestNeuron(nodeFinish))>=0)&&(getNearestNeuron(nodeStart)!=getNearestNeuron(nodeFinish)))
        {
            this->createElectricSynapse(nerveList[getNearestNeuron(nodeStart)], nerveList[getNearestNeuron(nodeFinish)]);
        }
        break;
    case 5:
        if (nodeDraw&&((getNearestNeuron(nodeStart)>=0)&&(getNearestNeuron(nodeFinish))>=0)&&(getNearestNeuron(nodeStart)!=getNearestNeuron(nodeFinish)))
        {
            this->createInhibitorSynapse(nerveList[getNearestNeuron(nodeStart)], nerveList[getNearestNeuron(nodeFinish)]);
        }
        break;
    case 6:
        if (nodeDraw&&((getNearestNeuron(nodeStart)>=0)&&(getNearestNeuron(nodeFinish))>=0)&&(getNearestNeuron(nodeStart)!=getNearestNeuron(nodeFinish)))
        {
            this->createChemicalSynapse(nerveList[getNearestNeuron(nodeStart)], nerveList[getNearestNeuron(nodeFinish)]);
        }
        break;
    }

    nodeDraw = false;
    this->update();
}
void QNeuronWindow::closeEvent (QCloseEvent * /*event*/)
{
    emit closeSignal();
}

void QNeuronWindow::rebuildIDs(void)
{
    for (int i=0; i<nerveList.length(); ++i)
    {
        nerveList[i]->setID(i);
    }
}
void QNeuronWindow::updatePropertyWidget(void)
{
    QList<int> removedNerves;
    int found = 0;

    for (int i=0; i<exNerveListLength; ++i)
    {
        found = 0;
        for (int j=0; j<nerveList.length(); ++j)
        {
            if (nerveList[j]->getID() == i) found++;
        }
        if (!found) removedNerves << i;
    }

    for (int i = removedNerves.length()-1; i>=0; --i)
    {
        propertyWidget->removeNerve(removedNerves[i]);
    }

    exNerveListLength = nerveList.length();
}
void QNeuronWindow::fillPropertyWidget(void)
{
    for (int i=0; i<nerveList.length(); ++i)
    {
        propertyWidget->addItem(nerveList[i]);
        if (nerveList[i]->isCurveVisible()) this->addCurve(i);
    }
}

void QNeuronWindow::addCurve(int _id)
{
    plot->addCurve();
    if (maxListCount < plot->getCurveNum())
    {
        maxListCount = maxListCount*10;
        delete [] maxValue;
        maxValue = new double[maxListCount];
        for (int i=0; i<maxListCount; ++i)
        {
            maxValue[i] = 0;
        }
    }
}
void QNeuronWindow::removeCurve(int _id)
{
    plot->removeCurve();
}

void QNeuronWindow::setMode0(void)
{
    mode = 0;
    this->setWindowTitle("Neuron Network - Free Mode Selected");

    if (!freeAction->isChecked()) freeAction->setChecked(true);
    if (neuronAction->isChecked()) neuronAction->setChecked(false);
    if (receptorAction->isChecked()) receptorAction->setChecked(false);
    if (transmitterAction->isChecked()) transmitterAction->setChecked(false);
    if (electricSynapseAction->isChecked()) electricSynapseAction->setChecked(false);
    if (inhibitorSynapseAction->isChecked()) inhibitorSynapseAction->setChecked(false);
    if (chemicalSynapseAction->isChecked()) chemicalSynapseAction->setChecked(false);
}
void QNeuronWindow::setMode1(void)
{
    mode = 1;
    this->setWindowTitle("Neuron Network - Neuron Mode Selected");

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (!neuronAction->isChecked()) neuronAction->setChecked(true);
    if (receptorAction->isChecked()) receptorAction->setChecked(false);
    if (transmitterAction->isChecked()) transmitterAction->setChecked(false);
    if (electricSynapseAction->isChecked()) electricSynapseAction->setChecked(false);
    if (inhibitorSynapseAction->isChecked()) inhibitorSynapseAction->setChecked(false);
    if (chemicalSynapseAction->isChecked()) chemicalSynapseAction->setChecked(false);
}
void QNeuronWindow::setMode2(void)
{
    mode = 2;
    this->setWindowTitle("Neuron Network - Receptor Mode Selected");

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (neuronAction->isChecked()) neuronAction->setChecked(false);
    if (!receptorAction->isChecked()) receptorAction->setChecked(true);
    if (transmitterAction->isChecked()) transmitterAction->setChecked(false);
    if (electricSynapseAction->isChecked()) electricSynapseAction->setChecked(false);
    if (inhibitorSynapseAction->isChecked()) inhibitorSynapseAction->setChecked(false);
    if (chemicalSynapseAction->isChecked()) chemicalSynapseAction->setChecked(false);
}
void QNeuronWindow::setMode3(void)
{
    mode = 3;
    this->setWindowTitle("Neuron Network - Transmitter Mode Selected");

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (neuronAction->isChecked()) neuronAction->setChecked(false);
    if (receptorAction->isChecked()) receptorAction->setChecked(false);
    if (!transmitterAction->isChecked()) transmitterAction->setChecked(true);
    if (electricSynapseAction->isChecked()) electricSynapseAction->setChecked(false);
    if (inhibitorSynapseAction->isChecked()) inhibitorSynapseAction->setChecked(false);
    if (chemicalSynapseAction->isChecked()) chemicalSynapseAction->setChecked(false);
}
void QNeuronWindow::setMode4(void)
{
    mode = 4;
    this->setWindowTitle("Neuron Network - Electic Synapse Mode Selected");

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (neuronAction->isChecked()) neuronAction->setChecked(false);
    if (receptorAction->isChecked()) receptorAction->setChecked(false);
    if (transmitterAction->isChecked()) transmitterAction->setChecked(false);
    if (!electricSynapseAction->isChecked()) electricSynapseAction->setChecked(true);
    if (inhibitorSynapseAction->isChecked()) inhibitorSynapseAction->setChecked(false);
    if (chemicalSynapseAction->isChecked()) chemicalSynapseAction->setChecked(false);
}
void QNeuronWindow::setMode5(void)
{
    mode = 5;
    this->setWindowTitle("Neuron Network - Inhibitor Synapse Mode Selected");

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (neuronAction->isChecked()) neuronAction->setChecked(false);
    if (receptorAction->isChecked()) receptorAction->setChecked(false);
    if (transmitterAction->isChecked()) transmitterAction->setChecked(false);
    if (electricSynapseAction->isChecked()) electricSynapseAction->setChecked(false);
    if (!inhibitorSynapseAction->isChecked()) inhibitorSynapseAction->setChecked(true);
    if (chemicalSynapseAction->isChecked()) chemicalSynapseAction->setChecked(false);
}
void QNeuronWindow::setMode6(void)
{
    mode = 6;
    this->setWindowTitle("Neuron Network - Chemical Synapse Mode Selected");

    if (freeAction->isChecked()) freeAction->setChecked(false);
    if (neuronAction->isChecked()) neuronAction->setChecked(false);
    if (receptorAction->isChecked()) receptorAction->setChecked(false);
    if (transmitterAction->isChecked()) transmitterAction->setChecked(false);
    if (electricSynapseAction->isChecked()) electricSynapseAction->setChecked(false);
    if (inhibitorSynapseAction->isChecked()) inhibitorSynapseAction->setChecked(false);
    if (!chemicalSynapseAction->isChecked()) chemicalSynapseAction->setChecked(true);
}

void QNeuronWindow::emitImpulse(void)
{
    this->spreadImpulse();
}

void QNeuronWindow::setGridStep(int _gridStep)
{
    gridStep = _gridStep;
    this->update();
}
void QNeuronWindow::setBinding(bool _hasBinding)
{
    hasBinding = _hasBinding;
}

void QNeuronWindow::reset(void)
{
    for (int i=nerveList.length()-1; i>=0; --i)
    {
        propertyWidget->removeNerve(i);
    }
    nerveList.clear();
    exNerveListLength = 0;
    for(int i=0; i<plot->getCurveNum(); ++i) plot->removeCurve();
    this->update();
}
void QNeuronWindow::save(void)
{
    QString fileName = QFileDialog::getSaveFileName(this, tr("Save Model") , "", "*.xml");

    if (!fileName.isEmpty())
    {
        QFile *file = new QFile(fileName);
        file->open(QIODevice::WriteOnly);
        QTextStream out(file);

        QDomDocument *xmlFile = new QDomDocument;
        QDomElement rootElement = xmlFile->createElement("ModelData");
        xmlFile->appendChild(rootElement);
        QDomElement nervesElement = xmlFile->createElement("Nerves");
        rootElement.appendChild(nervesElement);

        for (int i=0; i<nerveList.length(); ++i)
        {
            nervesElement.appendChild(this->xmlAddNerve(xmlFile, nerveList[i]));
        }

        out.setCodec("UTF-8");
        xmlFile->save(out, 4, QDomNode::EncodingFromTextStream);
        file->close();

        this->update();
    }
}
void QNeuronWindow::load(void)
{
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open Model"), "", "*.xml");
    if (!fileName.isEmpty())
    {
        this->reset();
        QFile file(fileName);
        QXmlInputSource xmlInputSource(&file);
        QXmlModelHandler xmlModelHandler;
        QXmlSimpleReader xmlSimpleReader;
        xmlSimpleReader.setContentHandler(&xmlModelHandler);
        xmlSimpleReader.parse(xmlInputSource);
        file.close();

        this->setNerveList(xmlModelHandler.getNerveList());

        this->update();
    }
}
void QNeuronWindow::stabilisation(void)
{
    bool ok = false;
    int cycles = 0;
    cycles = QInputDialog::getInteger(this, tr("Stabilisation"), tr("Cycles to pass:"), 5000, 0, 100000, 100, &ok);
    if (ok)
    {
        for (int k=0; k<cycles; ++k)
        {
            for (int i=0; i<nerveList.size(); ++i)
            {
                nerveList[i]->spreadMemPot();
            }
            for (int i=0; i<nerveList.size(); ++i)
            {
                nerveList[i]->rotMemPot();
            }
        }
    }
}

void QNeuronWindow::acceptChanges(void)
{
    emit nerveListChanged(nerveList);
}

void QNeuronWindow::showReceptorPotential(bool show)
{
    receptorPotentialVisible = show;
    this->update();
}
void QNeuronWindow::showSynapseDirection(bool show)
{
    synapseDirectionVisible = show;
    this->update();
}
void QNeuronWindow::showRelaxTime(bool show)
{
    relaxTimeVisible = show;
    this->update();
}

void QNeuronWindow::help(void)
{
    QMessageBox::question(this, tr("Help"), "Quick help text");
}
void QNeuronWindow::about(void)
{
    QMessageBox::information(this,"About","Model v<b>DATE</b>");
}

void QNeuronWindow::removeNerve(int _item)
{
    if (nerveList[_item]->getType()<4)
    {
        for (int i=nerveList[_item]->getReceiverList().length()-1; i>=0; --i)
        {
            for (int j=nerveList.length()-1; j>=0; --j)
            {
                if (nerveList[j]->getID()==nerveList[_item]->getReceiverList()[i]->getID())
                {
                    if (nerveList[j]->isCurveVisible()) this->removeCurve(j);
                    nerveList.removeAt(j);

                }
            }
        }

        for (int i=nerveList.length()-1; i>=0; --i)
        {
            if (nerveList[i]->getType()>3)
            {
                if (nerveList[i]->getReceiverList()[0]->getID() == _item)
                {
                    for (int j=nerveList.length()-1; j>=0; --j)
                    {
                        for (int k=nerveList[j]->getReceiverList().length()-1; k>=0; --k)
                        {
                            if (nerveList[j]->getReceiverList()[k]->getID() == nerveList[i]->getID())
                            {
                                nerveList[j]->removeReceiverAt(k);
                            }
                        }
                    }
                    if (nerveList[i]->isCurveVisible()) this->removeCurve(i);
                    nerveList.removeAt(i);
                }
            }
        }

        for (int i=nerveList.length()-1; i>=0; --i)
        {
            if (nerveList[i]->getID()==_item)
            {
                if (nerveList[i]->isCurveVisible()) this->removeCurve(i);
                nerveList.removeAt(i);
                break;
            }
        }
    }
    else if (nerveList[_item]->getType()>3)
    {
        if (nerveList[_item]->isCurveVisible()) this->removeCurve(_item);
        nerveList.removeAt(_item);
        for (int i=nerveList.length()-1; i>=0; --i)
        {
            for (int j=nerveList[i]->getReceiverList().length()-1; j>=0; --j)
            {
                if (nerveList[i]->getReceiverList()[j]->getID() == _item)
                {
                    nerveList[i]->removeReceiverAt(j);
                }
            }
        }
    }

    this->updatePropertyWidget();
    this->rebuildIDs();
    this->update();
}
